package com.zxhysy.log.annotation.advisor;

import com.zxhysy.log.annotation.LogIgnore;
import com.zxhysy.log.annotation.context.LogContext;
import com.zxhysy.log.annotation.context.MethodParameter;
import com.zxhysy.log.annotation.context.MethodResult;
import com.zxhysy.log.annotation.context.NetParameter;
import com.zxhysy.log.annotation.entity.LogOps;
import com.zxhysy.log.annotation.entity.LogRecord;
import com.zxhysy.log.annotation.service.ILogService;
import com.zxhysy.log.annotation.service.IOperatorGetService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * 拦截方法
 *
 * @author zhangxinhong
 * @since 2021/9/23 15:18
 */
@Slf4j
public class LogInterceptor implements MethodInterceptor {

    /**
     * 日志源
     */
    private final LogSource logSource;
    /**
     * 业务内部log，重写需要搞
     */
    private final ILogService logService;
    /**
     * 字段解析器
     */
    private final LogValueParser logValueParser;

    public LogInterceptor(LogSource logSource, ILogService logService, IOperatorGetService iOperatorGetService, LogFuncRegister logFuncRegister) {
        this.logSource = logSource;
        this.logService = logService;
        this.logValueParser = new LogValueParser(iOperatorGetService, logFuncRegister);
    }

    /**
     * 方法执行
     *
     * @param invocation 拦截断电
     * @return 执行结果
     */
    @Override
    public Object invoke(MethodInvocation invocation) {
        // 执行 方法
        return execute(new LogMethodInvoker(invocation));
    }

    /**
     * 执行
     *
     * @param executor 日志调用者
     * @return 目标方法执行结果
     */
    @SneakyThrows
    protected Object execute(LogMethodInvoker executor) {
        // 准备参数
        MethodParameter methodParameter = executor.getMethodParameter();
        NetParameter netParameter = executor.getNetParameter();
        // 准备注释信息
        Collection<LogRecord> logRecords = logSource.getLogOperations(methodParameter.getMethod(), methodParameter.getTargetClass());

        // 保证空元素在 执行方法前
        LogContext.putEmpty();
        // 执行方法
        MethodResult methodResult = executor.execute();

        // 保存消息
        try {
            // el 表达式解析
            logRecords.forEach(log -> {
                LogOps parse = logValueParser.parse(log, netParameter, methodParameter, methodResult);
                logService.save(parse);
            });
        } catch (Exception exception) {
            log.error("日志记录异常：" + exception.getMessage());
        } finally {
            // 清除
            LogContext.clean();
        }

        if (Boolean.FALSE.equals(methodResult.isSuccess())) {
            throw methodResult.getThrowable();
        }
        return methodResult.getResult();
    }
}
